////////////////////////////////////////////////////////////////////////////////
//
// I2C_init()           initializes the IIC driver
// I2C_start()          issues a START condition
// I2C_stop()           issues a STOP  conditiom
// I2C_tx_byte( data )  transmits a byte, returns aknoledge
// I2C_rx_byte( ack)    receives a byte, if ack=TRUE acknowledges the sender
// 
////////////////////////////////////////////////////////////////////////////////

#include <MC68HC908JK3.h>
#include "i2c.h"

static void I2C_tx_bit_1(void);         //transmits a logic 1
static void I2C_tx_bit_0(void);         //transmits a logic 0
static unsigned char I2C_rx_bit(void);  //receives a bit                        

////////////////////////////////////////////////////////////////////////////////
// CONFIGURATION SECTION
// the following code provides the methods for setting the IIC SDA (data) and
// SCL (clock) lines, and a routine to time the bus speed.
// Change them to configure for the processr/pins you are using
////////////////////////////////////////////////////////////////////////////////


#define SCL_high   {PTB_PTB6 = 1; I2C_wait();}
#define SCL_low    {PTB_PTB6 = 0; I2C_wait();}
#define SCL_output {DDRB_DDRB6 = 1;} 

#define SDA_high   {PTB_PTB7 = 1; I2C_wait();}
#define SDA_low    {PTB_PTB7 = 0; I2C_wait();}
#define SDA_output {DDRB_DDRB7 = 1;}
#define SDA_input  {DDRB_DDRB7 = 0;}
#define SDA_value  (PTB_PTB7)
 

static void I2C_wait(void)
{
  unsigned char i;
  for (i=0; i<10; i++)
  ;;
}

////////////////////////////////////////////////////////////////////////////////
// END OF CONFIGURATION SECTION
// you should not need to change anything below this line
////////////////////////////////////////////////////////////////////////////////

void I2C_init(void)         //initializes IIC system
{
  SCL_output;
  SDA_output;
  I2C_stop();
}

void I2C_start(void)        //issues a START condition
{
  SDA_output;
  SDA_high;
  SCL_high;
  SDA_low;
}

void I2C_stop(void)         //issues a STOP condition
{
  SDA_output;
  SDA_low;
  SCL_high;
  SDA_high;
}

//transmits a byte, returns device aknowledge

unsigned char I2C_tx_byte(unsigned char B)
{       
  unsigned char i;
  for(i=0; i<8; i++){
    if (B & 0x80)
      I2C_tx_bit_1();
    else
      I2C_tx_bit_0();
  B = B << 1;
  };

  i = I2C_rx_bit();
  return(i);
}

//receives a byte, if acknowledge = 1 generates the ACK bit

unsigned char I2C_rx_byte(unsigned char acknowledge)
{
  unsigned char i, retval;
  retval = 0;
  for(i=0; i<8; i++)                 
  { 
          retval = (retval << 1);
          if (I2C_rx_bit()) retval++;
  };
  if (acknowledge) 
  {       I2C_tx_bit_0();        
  }
  else
  {       I2C_tx_bit_1();        
  };
  return retval;
}

////////////////////////////////////////////////////////////////////////////////
// BIT-LEVEL, INTERNAL USE ROUTINES FOLLOW
////////////////////////////////////////////////////////////////////////////////

static void I2C_tx_bit_1(void)          //transmits a logic 1
{
  SCL_low;
  SDA_output;
  SDA_high;
  SCL_high;
  SCL_low;    
} 

static void I2C_tx_bit_0(void)          //transmits a logic 0
{
  SCL_low;
  SDA_output;
  SDA_low;
  SCL_high;
  SCL_low;
}
                         
static unsigned char I2C_rx_bit(void)   //receives a bit,returns ACK status                        
{
  unsigned char retval;
  SDA_input;
  SCL_low;
  SCL_high;        
  retval = SDA_value;
  SCL_low;
  return retval;
}
